#include <iostream>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>

using namespace std;

//命名管道
//1.匿名管道应用的一个限制就是只能在具有共同祖先(具有血缘关系)的进程间通信
//2.如果我们想在不相关的进程之间交换数据,可以使用FIFO文件来做这项工作
//它经常被称为命名管道
//命名管道是一种特殊类型的文件

//创建命名管道可以从命令行上创建,采用如下的命令:
//mkfifo filename

//命名管道也可以从程序里创建,相关的函数是:
//int mkfifo(const char* filename, mode_t mode);
//filename:创建管道的路径
//mode:设置管道的权限(会和系统的权限掩码进行按位与)

//匿名管道和命名管道的区别
//1.匿名管道由pipe函数创建并打开
//2.命名管道由mkfifo函数创建,打开用open
//3.FIFO与pipe之间的唯一区别就是它们的创建与打开的方式不同,一旦这些工作完成之后,它们具有相同的语义

//命名管道的打开规则
//1.如果当前打开操作是为读而打开FIFO时
//O_NONBLOCK disable：阻塞直到有相应进程为写而打开该FIFO
//O_NONBLOCK enable：立刻返回成功
//2.如果当前打开操作是为写而打开FIFO时
//O_NONBLOCK disable：阻塞直到有相应进程为读而打开该FIFO
//O_NONBLOCK enable：立刻返回失败，错误码为ENXIO

//用命名管道实现文件拷贝

int main()
{
    //将原文件以读的方式打开
    int infd = open("./source.txt", O_RDONLY);
    if (infd == -1)
    {
        perror("open fail");
        exit(1);
    }

    //创建一个管道
    mkfifo("./cp_fifo", 0644);

    //将管道以写的方式打开
    int outfd = open("./cp_fifo", O_WRONLY);
    if (outfd == -1)
    {
        perror("open fail");
        exit(2);
    }

    char buf[1024];
    int ret_r;
    //将原文件里面的读取的数据写入管道中
    while((ret_r = read(infd, buf, sizeof(buf))) > 0)
    {
        write(outfd, buf, ret_r);
    }

    close(infd);
    close(outfd);

    return 0;
}
